home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Applications / ARTAbrot 1.0 / BrotCode.c < prev    next >
Text File  |  1993-08-24  |  8KB  |  280 lines

  1. /************************************************************************/
  2. /*                                                                        */
  3. /*    FILE:        BrotCode.c -- Code for computing Mandelbrots.            */
  4. /*                                                                        */
  5. /*    PURPOSE:    Code to communicate with DSP to calculate Mandelbrots.    */
  6. /*                                                                        */
  7. /*    AUTHOR:        George T. Warner                                        */
  8. /*                                                                        */
  9. /*    REVISIONS:                                                            */
  10. /*    08/22/93    First version.                                            */
  11. /*                                                                        */
  12. /************************************************************************/
  13.  
  14. #include <Quickdraw.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include "DSPManager.h"
  19. #include "DSPConstants.h"
  20. #include "BrotCode.h"
  21. #include "ComUtil_ARTAbrot.h"    /* Common */
  22. #include "AB_Alert.h"
  23.  
  24. struct DSPCPUDeviceParamBlk pb, *pbPtr;
  25. DSPTaskRefNum taskRefNum;
  26. DSPModuleRefNum modRefNum;
  27. DSPSectionRefNum BroBufRefNum;
  28.  
  29. /* Offscreen pixMap stuff. */
  30. extern GWorldPtr offscreenGWorld;    /* Off screen graphics world. */
  31. extern Rect    GWorldBounds;            /* Boundaries of graphics world. */
  32.  
  33. static char *brot_data;
  34.  
  35. #define nil 0
  36. #define NumElements 128
  37.  
  38. typedef struct
  39. {
  40.     long Startflag;
  41.     long Doneflag;
  42.     long Points;
  43.     long Maxiter;
  44.     float Xstart;
  45.     float Delta;
  46.     float Ystart;
  47.     long Inited;
  48.     short OutputData[640];
  49. }
  50. MyPBuff;
  51.  
  52. MyPBuff *mypbuffptr;
  53.  
  54.  
  55. pascal void fatalError(DSPMessagePtr errorBlockPtr)
  56. {
  57. #pragma unused (errorBlockPtr)
  58. char tmp_string[256];
  59.  
  60.     sprintf(tmp_string, "MessageActionProc called.");
  61.     AB_Alert(tmp_string);
  62. }
  63.  
  64. void solve_brot()
  65. {
  66. Ptr base_addr;
  67. long row_bytes;    /* Used for PixMap calculations. */
  68. Rect rect_to_copy;
  69. unsigned char *pixel_address;
  70. int got_data;
  71. short *data_mem = nil; /* Array for uploading Mandelbrot data into. */
  72. long xpoint;
  73. unsigned long ypoint;
  74. int xpix, ypix;
  75. float fxdelta, fydelta;
  76. char tmp_string[256];
  77. double distance_per_pixel, fheight;
  78. OSErr err;
  79.     
  80.     SetPort(WPtr_ARTAbrot);
  81.     
  82.     xpix = WPtr_ARTAbrot->portRect.right-WPtr_ARTAbrot->portRect.left;
  83.     ypix = WPtr_ARTAbrot->portRect.bottom-WPtr_ARTAbrot->portRect.top;
  84.     distance_per_pixel = fwidth/(double)xpix;
  85.     fheight = (double)ypix * distance_per_pixel;
  86.  
  87.     pb.pbhDeviceIndex        = 0;                    /* Just use device 0. */
  88.     pb.pbhClientPermission    = kdspReadPermission;    /* Not sure what this means. */
  89.     pb.pbhDeviceICON        = nil;                    /* No icon desired. */
  90.     pb.pbhClientICON         = nil;
  91.     pb.cpuClientMessageActionProc = fatalError;
  92.     BlockMove("\pARTAbrot", pb.pbhClientName, 32);
  93.     
  94.     pbPtr = &pb;
  95.     
  96.     /* Get information on DSP 0. */
  97.     if (DSPGetIndexedCPUDevice(pbPtr)) {
  98.         sprintf(tmp_string, "Failure: No DSPs attached!");
  99.         AB_Alert(tmp_string);
  100.         return;
  101.     }
  102.  
  103.     /* Open device driver. */
  104.     if (DSPOpenCPUDevice(pbPtr)) {
  105.         sprintf(tmp_string, "Failure opening DSP device driver.");
  106.         AB_Alert(tmp_string);
  107.         return;
  108.     }
  109.     
  110.     /* Create a new task structure. */
  111.     if (DSPNewTask(pbPtr, &fatalError, "\pMandelbrot", &taskRefNum)) {
  112.         sprintf(tmp_string, "Failure creating new task structure.");
  113.         AB_Alert(tmp_string);
  114.         goto close_device;
  115.     }
  116.  
  117.     /* Load a module into the task structure. */
  118.     err = DSPLoadModule("\pmbrot",     /* Load MBrot resource. */
  119.                     taskRefNum,     /* Pass task structure reference number. */
  120.                     kdspAnyPositionInsert, /* Put it anywhere. */
  121.                     NULL,             /* Optional reference module number. */
  122.                     &modRefNum,     /* Pointer to get module reference number. */
  123.                     NumElements);    /* Scale multiplier (not sure about this yet). */
  124.     if (err) {
  125.         sprintf(tmp_string, "Failure loading MBrot module.");
  126.         AB_Alert(tmp_string);
  127.         goto dispose_task;
  128.     }
  129.  
  130.     /* Insert Task into Task List */
  131.     if (DSPInsertTask(pbPtr, taskRefNum, kdspAnyPositionInsert, kdspTimeShare, NULL)) {
  132.         sprintf(tmp_string, "Failure inserting task.");
  133.         AB_Alert(tmp_string);
  134.         goto dispose_task;
  135.     }
  136.  
  137.     /* Get section reference numbers for the parameter buffer. */
  138.     if (DSPGetSection(modRefNum,"\pbrobuf",&BroBufRefNum)) {
  139.         sprintf(tmp_string, "Failure getting parameter buffer reference number.");
  140.         AB_Alert(tmp_string);
  141.         goto dispose_task;
  142.     }
  143.  
  144.     /* Get pointer to parameter buffer. */
  145.     err = DSPGetSectionData(BroBufRefNum,(Ptr *)&mypbuffptr);
  146.     if (err) {
  147.         sprintf(tmp_string, "Failure getting parameter buffer pointer.");
  148.         AB_Alert(tmp_string);
  149.         goto dispose_task;
  150.     }
  151.  
  152.     /* Allocate buffer to hold one line of data. */
  153.     data_mem = (short *)calloc(xpix, sizeof(short));
  154.     if(!data_mem) {
  155.         sprintf(tmp_string, "Failure allocating data buffer.");
  156.         AB_Alert(tmp_string);
  157.         goto remove_task;
  158.     }
  159.  
  160.     fydelta = fxdelta = fwidth/xpix;
  161.     /* Download left coordinate of image. */
  162.     mypbuffptr->Xstart = fxcenter-(fwidth/2);
  163.     mypbuffptr->Delta = fxdelta;
  164.     /* Download bottom coordinate of image. */
  165.     mypbuffptr->Ystart = fycenter-(fheight/2);
  166.     /* Tell num. of pixels to do. */
  167.     mypbuffptr->Points = xpix;
  168.     mypbuffptr->Maxiter = fiters;
  169.     /* Start with first line. */
  170.     mypbuffptr->Doneflag = 0;
  171.     mypbuffptr->Startflag = 0;
  172.  
  173.     /* Start calculations! */
  174.     if (DSPSetTaskActive(taskRefNum)) {
  175.         sprintf(tmp_string, "Failure setting task active.");
  176.         AB_Alert(tmp_string);
  177.         goto remove_task;
  178.     }
  179.  
  180.     HideCursor();
  181.     
  182.     LockPixels(offscreenGWorld->portPixMap);
  183.     row_bytes = ((**(offscreenGWorld->portPixMap)).rowBytes) & 0x3fff;
  184.     base_addr = GetPixBaseAddr(offscreenGWorld->portPixMap);
  185.  
  186.     /* Wait for DSP module to initialize. */
  187.     while (!mypbuffptr->Inited) {
  188.         /* Force stop waiting if user hits command-period. */
  189.         if (check_stop()) {
  190.             goto remove_task;
  191.         }
  192.     }
  193.  
  194.     /* Start processing first line. */
  195.     mypbuffptr->Startflag = 1;
  196.  
  197.     for (ypoint=1; ypoint <= ypix; ypoint++) {
  198.         got_data = TRUE;
  199.         /* I'm actually going to poll the DSP until it completes.    */
  200.         /* This could be better, I know, but what do you expect        */
  201.         /* for brand-new, hot-off-the-press, source code?            */
  202.         /* At least I let you abort with Command-period.            */
  203.         while (!mypbuffptr->Doneflag) {
  204.             /* Force stop waiting if user hits command-period. */
  205.             if (check_stop()) {
  206.                 got_data = FALSE;
  207.                 break;
  208.             }
  209.         }
  210.         if (got_data) {
  211.             /* Copy data from DSP buffer. */
  212.             BlockMove(mypbuffptr->OutputData, data_mem, xpix * sizeof(short));
  213.  
  214.             if (ypoint != ypix) { /* Don't start new line if we don't need it. */
  215.                 /* Download new Y coordinate. */
  216.                 mypbuffptr->Ystart = (fycenter-(fheight/2)) + (ypoint * fxdelta);
  217.                 /* Acknowledge that last line was completed. */
  218.                 mypbuffptr->Doneflag = 0;
  219.                 /* Tell it to go. */
  220.                 mypbuffptr->Startflag = 1;
  221.             }
  222.  
  223.             /* Convert results to bytes for indexed color display. */
  224.             pixel_address = (unsigned char *)((unsigned long)base_addr + ((ypoint-1) * (unsigned long)row_bytes));
  225.             for (xpoint=0; xpoint < xpix; xpoint++)
  226.                 *pixel_address++ = data_mem[xpoint];
  227.  
  228.             SetRect(&rect_to_copy, GWorldBounds.left, GWorldBounds.top+ypoint-1, GWorldBounds.right, GWorldBounds.top+ypoint); /* left, top, right, bottom */
  229.         
  230.             /* Display line on screen. */
  231.             CopyBits((BitMap *)*offscreenGWorld->portPixMap, &(WPtr_ARTAbrot->portBits), &(rect_to_copy), &(rect_to_copy), srcCopy, 0);
  232.         }
  233.         else {
  234.             SysBeep(1);
  235.             break;
  236.         }
  237.     }
  238.  
  239.     UnlockPixels(offscreenGWorld->portPixMap);
  240.  
  241.     /* Deactivate the Task */
  242.     if (DSPSetTaskInactive(taskRefNum)) {
  243.         ShowCursor();
  244.         sprintf(tmp_string, "Failure setting task inactive.");
  245.         AB_Alert(tmp_string);
  246.     }
  247.  
  248.     if (data_mem)
  249.         free(data_mem);
  250.  
  251. remove_task:
  252.     /* Remove the Task */
  253.     if (DSPRemoveTask(taskRefNum)) {
  254.         ShowCursor();
  255.         sprintf(tmp_string, "Failure removing task.");
  256.         AB_Alert(tmp_string);
  257.     }
  258.  
  259. dispose_task:
  260.     /* Dispose the Task */
  261.     if (DSPDisposeTask(taskRefNum)) {
  262.         ShowCursor();
  263.         sprintf(tmp_string, "Failure disposing task.");
  264.         AB_Alert(tmp_string);
  265.     }
  266.  
  267. close_device:
  268.     /* Close the CPU Device */
  269.     if (DSPCloseCPUDevice(pbPtr)) {
  270.         ShowCursor();
  271.         sprintf(tmp_string, "Failure closing DSP driver.");
  272.         AB_Alert(tmp_string);
  273.     }
  274.  
  275.     new_coordinates=FALSE;
  276.     ShowCursor();
  277. } /*solve*/
  278.  
  279.  
  280.